package com.itfreer.arcgis;

import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.FeatureTable;
import com.esri.arcgisruntime.data.Field;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.data.ShapefileFeatureTable;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.itfreer.arcgis.query.AttributeListener;
import com.itfreer.utils.LogUtils;
import com.itfreer.utils.MessageUtils;
import com.itfreer.utils.StringUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;


/**
 * 矢量数据表对象
 */
public class FeatureTableUtils
{
    /***
     * 属性查询
     * @param featureTable 查询图层
     * @param params 查询条件
     */
    public static void AttributeQuery(final FeatureTable featureTable, String params, final AttributeListener listener)
    {
        QueryParameters queryParams = new QueryParameters();
        if(StringUtils.IsNullOrEmpty(params))
            params = "1=1";
        queryParams.setWhereClause(params);

        final ListenableFuture<FeatureQueryResult> future = featureTable.queryFeaturesAsync(queryParams);
        future.addDoneListener(new Runnable()
        {
            @Override public void run()
            {
                try
                {
                    // 获取查询结果
                    FeatureQueryResult result = future.get();

                    List<Feature> features = new ArrayList<Feature>();
                    Iterator<Feature> iterator = result.iterator();
                    Feature feature;
                    while (iterator.hasNext())
                    {
                        feature = iterator.next();
                        features.add(feature);
                    }
                    if(listener != null)
                        listener.execute(featureTable.getTableName(),features);
                }
                catch (InterruptedException | ExecutionException e)
                {
                    LogUtils.Print("Error in FeatureQueryResult: " + e.getMessage(), LogUtils.Lever.Error);
                    MessageUtils.Show("SQL异常！");
                }
            }
        });
    }

    /**
     * 打开本地的shape文件转成FeatureTable
     * @param path
     * @return
     */
    public static FeatureTable GetFeatureTableFormShape(String path)
    {
        ShapefileFeatureTable shapefileFeatureTable = new ShapefileFeatureTable(path);
        return  shapefileFeatureTable;
    }

    /**
     * 判断是否为系统字段
     * @param featureTable 矢量图层对象
     * @param fieldName 字段名
     * @return
     */
    public static Boolean IsSystemField(FeatureTable featureTable, String fieldName)
    {
        if(StringUtils.IsNullOrEmpty(fieldName))
            return  false;
        Field field = featureTable.getField(fieldName);
        if(field == null)
            return  null;

        if(field.getFieldType().equals(Field.Type.OID))
            return  true;

        if(field.getFieldType().equals(Field.Type.GEOMETRY))
            return  true;

        if(field.getFieldType().equals(Field.Type.GLOBALID))
            return  true;

        if(field.getFieldType().equals(Field.Type.GUID))
            return  true;

        if(fieldName.toUpperCase().equals("SHAPE_LENGTH"))
            return  true;

        if(fieldName.toUpperCase().equals("SHAPE_AREA"))
            return  true;

        return  false;
    }

    /**
     * 获取OID字段名
     * @param featureTable 矢量图层对象
     * @return
     */
    public static String GetOIDFieldName(FeatureTable featureTable)
    {
        Field field = GetOIDField(featureTable);
        if(field == null)
            return  "";
        else
            return  field.getName();
    }

    /**
     * 获取OID字段名
     * @param featureTable 矢量图层对象
     * @return
     */
    public static Field GetOIDField(FeatureTable featureTable)
    {
        if(featureTable == null)
            return  null;

        for(Integer i = 0;i<featureTable.getFields().size();i++)
        {
            if(featureTable.getFields().get(i).getFieldType().equals(Field.Type.OID))
                return  featureTable.getFields().get(i);
        }
        return  null;
    }

    /**
     * 创建元素
     * @param geometry 图形对象
     * @param attributes 属性集合
     * @param featureTable 要素表
     */
    public static void AddFeature(Geometry geometry, Map<String,Object> attributes,FeatureTable featureTable)
    {
        if(geometry == null || geometry.isEmpty())
            return;

        if(!GeometryEngine.isSimple(geometry))
            return;

        if(featureTable == null || !featureTable.canAdd())
            return;

        Feature  feature = featureTable.createFeature();

        //如果有属性值，则遍历设置属性值
        //TODO song 后续添加属性类型校验，和系统字段如objectid， shape_length等字段过滤
        if(attributes != null && attributes.size()>0)
        {
            for (String in : attributes.keySet())
            {
                if(feature.getAttributes().containsKey(in))
                {
                    Object value = attributes.get(in);
                    feature.getAttributes().put(in,value);
                }
             }
        }

        feature.setGeometry(geometry);
        featureTable.addFeatureAsync(feature);
    }

    /**
     * 创建元素
     * @param feature 要素对象
     * @param featureTable 要素表
     */
    public static void UpdateFeature(FeatureTable featureTable,Feature feature)
    {
        if(feature == null || feature.getGeometry() == null || feature.getGeometry().isEmpty())
            return;

        //多部分不允许保存
        if(!GeometryEngine.isSimple(feature.getGeometry()))
            return;

        if(featureTable == null || !featureTable.canAdd())
            return;

        if(!featureTable.canUpdate(feature))
            return;

        featureTable.updateFeatureAsync(feature);
    }

    /**
     * 删除选择要素
     * @param featureTable
     * @param feature
     */
    public static void DeleteFeature(FeatureTable featureTable,Feature feature)
    {
        if(featureTable == null || feature == null)
            return;

        if(!featureTable.canDelete(feature))
            return;

        featureTable.deleteFeatureAsync(feature);
    }
}
